package cn.lsc.service.impl;

import cn.lsc.constants.RedisRegistConstant;
import cn.lsc.domain.*;

import cn.lsc.dto.RedisRegisterDto;
import cn.lsc.enums.GlobaEnums;
import cn.lsc.feign.commonFeign;
import cn.lsc.feign.uaaFeignService;
import cn.lsc.mapper.UserMapper;
import cn.lsc.result.JSONResult;
import cn.lsc.service.IUserService;
import cn.lsc.util.AssertUtil;
import cn.lsc.util.BitStatesUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import dto1.PhoneRegisterDto;
import cn.lsc.dto.userCode;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author lsc
 * @since 2022-08-26
 */
@Service
//@Transactional

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private uaaFeignService uaaFeignService;

    @Autowired
    private  UserAccountServiceImpl userAccountService;

    @Autowired
    private  UserBaseInfoServiceImpl userBaseInfoService;

    @Autowired
    private UserGrowLogServiceImpl userGrowLogService;

    @Autowired
    private commonFeign commonFeign;

//黑名单和推荐码
    @Override
    @GlobalTransactional
    public void register(PhoneRegisterDto phoneRegisterDto) {
        String code1 = phoneRegisterDto.getCode();
        Long referId = phoneRegisterDto.getUserid();
        String smsCode = phoneRegisterDto.getSmsCode();
        String mobile = phoneRegisterDto.getMobile();
        Integer regChannel = phoneRegisterDto.getRegChannel();
        String password = phoneRegisterDto.getPassword();

        //黑名单校验
        JSONResult byphone = commonFeign.findByphone(mobile);
        Object data = byphone.getData();

        AssertUtil.isNull(byphone.getData(),GlobaEnums.USER_BACKLIST_ERROR);


        //校验推荐码
       userCode userCode= userMapper.findByCode(code1);
       //校验是否为空
       AssertUtil.isNull(userCode,GlobaEnums.CODE_ONEPIES_ERROR);


        //1.使用303对参数进行校验
        //判断图形验证码是否过期
        // 2. 图形验证码校验
        //2获取redis中得手机验证码，判断是否存在确定
        String key = String.format(RedisRegistConstant.PHONE_REGISTER_PREFIX,mobile);
        Object codeTmp = redisTemplate.opsForValue().get(key);
        //2.1判断验证码是否存在 ，不存在就抛出自定义错误码
        AssertUtil.isNotNull(codeTmp, GlobaEnums.CODE_OUTTIME_ERROR);
        //2.2将前端传过来得code强转成RedisRegisterDto Long类型
        RedisRegisterDto code=(RedisRegisterDto) codeTmp;
        //2.3不为空之后就开始判断前端输入的验证码是否与redis存入得一直，不一致泽爆出异常
        AssertUtil.isEquals(code.getCode(),smsCode,GlobaEnums.CODE_NOTOK_ERROR);
        //3.判断前端传来得手机号在数据库中是否存在
        User user=selectByphone(mobile);
        //判断手机号是否被注册，如果有了就直接抛出错误码
        AssertUtil.isNull(user,GlobaEnums.PHONE_ISNULL_ERROR);

        //4.保存login
        Login login = new Login();
        login.setUsername(mobile);
        login.setPassword(password);
        login.setType(1);
        login.setEnabled(true);
        JSONResult jsonResult = uaaFeignService.saveOrUpdate(login);
        //4.1判断是否响应得时熔断数据，如果时直接抛出异常
        AssertUtil.isTrue(jsonResult.isSuccess(),GlobaEnums.Error);
        Long loginId =Long.valueOf(jsonResult.getData().toString()) ;
        AssertUtil.isNotNull(loginId,GlobaEnums.USER_REGISTER_ERROR);
        //保存USer
        User saveUser=saveUser(loginId,mobile);
        Long userId = saveUser.getLoginId();
        AssertUtil.isNotNull(userId,GlobaEnums.USER_REGISTER_ERROR);
        //4.2保存User相关表
        saveUserAccount(userId, userAccountService);
        // 保存UserBaseInfo相关表
        saveUserBaseInfo(regChannel, userId,referId);
        // 保存UserGrowLog相关表
        saveUserGrowLog(userId);

        //保存
        userCode code11 = new userCode();
        code11.setCode(code1);
        code11.setUserId(referId);
        userMapper.add(code11);
    }

    private void saveUserGrowLog(Long userId) {
        UserGrowLog userGrowLog = new UserGrowLog();
        userGrowLog.setUserId(userId);
        userGrowLog.setCreateTime(new Date().getTime());
        userGrowLogService.insert(userGrowLog);
    }

    private void saveUserBaseInfo(Integer regChannel, Long userId,Long referId) {

        UserBaseInfo userBaseInfo = new UserBaseInfo();
        userBaseInfo.setReferId(referId);
        userBaseInfo.setRegChannel(regChannel);
        userBaseInfo.setCreateTime(new Date().getTime());
        userBaseInfo.setId(userId);
        userBaseInfoService.insert(userBaseInfo);
    }

    private static void saveUserAccount(Long userId, UserAccountServiceImpl userAccountService) {
        UserAccount userAccount = new UserAccount();
        userAccount.setId(userId);
        userAccount.setCreateTime(new Date().getTime());
        userAccount.setPassword("123456");
        userAccountService.insert(userAccount);
    }

    private User saveUser(Long loginId,String mobile) {
        User user=new User();
        user.setPhone(mobile);
        user.setNickName(mobile);
        user.setCreateTime(new Date().getTime());
        user.setLoginId(loginId);
        // 注册成功+ 激活成功
        long bitState = BitStatesUtils.addState(BitStatesUtils.OP_REGISTED, BitStatesUtils.OP_ACTIVED);
        // 已有状态 + 手机认证
        bitState = BitStatesUtils.addState(bitState, BitStatesUtils.OP_AUTHED_PHONE);
        user.setBitState(bitState);
        insert(user);
        return user;
    }

    private User selectByphone(String mobile) {
        //wapper条件构造器
       Wrapper<User> wrapper = new EntityWrapper<>();
        wrapper.eq("phone",mobile);
        //构造器根据条件去查询数据库比对，查询返回一条数据
        return selectOne(wrapper);
    }
}
